package me.luger.core.aspect.log;

import me.luger.core.auth.identity.UserInfoGetter;
import me.luger.core.commom.util.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by Administrator on 2016/12/11 0011.
 */
@Aspect
@Component
public class OpLogAspect {

    @Autowired(required = false)
    private UserInfoGetter userInfoGetter;

    @Pointcut("@annotation(me.luger.core.aspect.log.OpLog)")
    public void opLog(){}

    @Around("opLog()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        try{
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod(); //获取被拦截的方法
            String methodName = method.getName(); //获取被拦截的方法名
            Object[] args = pjp.getArgs();
            String[] parameterNames = ReflectUtil.getMethodParameterNames(method);

            OpLog opLog = method.getAnnotation(OpLog.class);
            if(null == opLog){
                return pjp.proceed();
            }

            String name = opLog.name();
            String detail = opLog.detail();
            String after = opLog.after();//方法执行完在记录日志，此时detail中的spel应该有返回值result相关的表达式


            Map<String,Object> variableMap = new HashMap<String,Object>();

            HttpServletRequest request = ServletUtil.getRequest();
            if(null != request){
                Map<String,String[]> requestParameterMap = request.getParameterMap();
                Map<String,String> parameterMap = parseParameterMap(requestParameterMap);
                Object obj = request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
                Map<String,String> pathVariablesMap = (Map<String, String>) obj;
                variableMap.putAll(parameterMap);
                variableMap.putAll(pathVariablesMap);
            }
            for(int i=0;i<parameterNames.length;i++){
                variableMap.put(parameterNames[i],args[i]);
            }

            if(StringUtil.isNotBlank(detail)){
                detail = SpelUtil.parseKey2String(detail,variableMap);
            }


            Object retObj = pjp.proceed();

            if(StringUtil.isNotBlank(after)){
                variableMap.put("result",retObj);
                after = SpelUtil.parseKey2String(after,variableMap);
            }

            Map<String,Object> logMap = new HashMap<String,Object>();
            logMap.put("name",name);
            logMap.put("detail",detail);
            logMap.put("after",after);
            logMap.put("userInfo",userInfoGetter.getUserInfo());

            LogUtil.opLog(JsonUtil.toString(logMap));

            return retObj;
        }catch (Exception e){
            LogUtil.errorLog(e,"OpLogAspect.doAround error");
            return pjp.proceed();
        }
    }


    private Map<String,String> parseParameterMap(Map<String,String[]> parameterMap){
        Map<String,String> newMap = new HashMap<String,String>();

        Set<String> keys = parameterMap.keySet();
        for(String key : keys){
            String[] values = parameterMap.get(key);
            if(null != values && values.length > 0){
                newMap.put(key,values[0]);
            }
        }
        return newMap;
    }

}
